#ifndef _PARTICLE_SYS
#define _PARTICLE_SYS

#ifdef _PARTICLES
#include "stdafx.h"
#include "Utility.h"
#include "GridField.h"

class NSSolver;
class DecoScene;

enum RenderProfileT
{
	RP_Pressure,
	RP_Vorticity,
	RP_PlainColor
};

class ParticleTrace
{
private:
	int mNumTraceSteps;
	FixLengthQueue<vector3> mPosTrace;
	FixLengthQueue<vector3> mVelTrace;

public:
	ParticleTrace();
	ParticleTrace(const ParticleTrace& rhs);
	~ParticleTrace();
	void SetTraceSteps(int steps);
	const vector3& GetPosAtIthStep(int ithStep) const;
	const vector3& GetVelAtIthStep(int ithStep) const;
	void GetWholeTrace(std::vector<vector3>& trace) const;
	void Update(const vector3& pos, const vector3& vel);
	const ParticleTrace& operator=(const ParticleTrace& rhs);
};



class Particle
{
public:
	vector3 m_pos;
	vector3 m_prePos;
	vector3 m_velocity;
	double m_vorticity;
	int m_life;
	ParticleTrace m_trace;
	Particle();
	Particle(const vector3& pos);

	friend DecoArchive& operator<< (DecoArchive& Ar, const Particle& p)
	{
		return Ar << p.m_pos << p.m_prePos << p.m_velocity;
	}
	friend DecoArchive& operator>> (DecoArchive& Ar, Particle& p)
	{
		return Ar >> p.m_pos >> p.m_prePos >> p.m_velocity;
	}

};

class ParticleSys
{
private:

	GridField* m_grid;
	NSSolver* m_solver;
	DecoScene* m_scene;
	list<Particle> particles;
	void fillParticlesInCube(const vector3& basePos, DOUBLE stepSize, double numParPerCell);
public:
	ParticleSys() : m_grid(NULL), m_solver(NULL), m_scene(NULL)

	{

	}
	~ParticleSys()
	{
	}
	void SetScene(DecoScene* scene);
	void SetGridField( GridField* gridField );
	void SetSolver(NSSolver* solver);
	void AddParticle(const Particle& p);
	void Evolve ();
	void Render (DecoRenderInterface* RI, DecoLight** Lights, UINT numEffectiveLights, RenderProfileT profile = RP_PlainColor);
	void FillParticles(BYTE*** solidElements, INT numSlices, INT height, INT width);
	void FillParticles();
	void FillParticlesInBox(const Box& box);
	void EraseParticlesOutsideBox(const Box& box);
	const list<Particle>& GetAllParticles();
	void DumpRIB(const char* filename);
	void Serialize(DecoArchive& Ar) const;
	void Deserialize(DecoArchive& Ar);
	void ReadFromFile();
	void DumpParticleTraces(const string& filePath);
	//static ParticleSys* GetSingleton();
	//static void DestroySingleton();
};
#endif
#endif